package cn.huiyunche.base.service.interfaces.impl;

import cn.huiyunche.base.service.constant.App;
import cn.huiyunche.base.service.constant.WeixinConstant;
import cn.huiyunche.base.service.enums.EnabledEnum;
import cn.huiyunche.base.service.enums.UserTypeEnum;
import cn.huiyunche.base.service.framework.security.JwtAuthenicationFilter;
import cn.huiyunche.base.service.framework.security.JwtUtils;
import cn.huiyunche.base.service.framework.utils.HYCUtils;
import cn.huiyunche.base.service.framework.utils.HttpUtils;
import cn.huiyunche.base.service.framework.utils.WeixinUtils;
import cn.huiyunche.base.service.interfaces.WeixinService;
import cn.huiyunche.base.service.mappers.SUserMapper;
import cn.huiyunche.base.service.model.SUser;
import cn.huiyunche.base.service.model.SUserExample;
import cn.huiyunche.base.service.vo.*;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

/**
 * 微信对外接口服务层
 *
 * @author hdy [Tuffy]
 */
@Service

public class WeixinServiceImpl implements WeixinService {

    @Autowired
    private SUserMapper userMapper = null;

    /**
     * 初始化微信url认证
     *
     * @param signature 微信加密签名
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @return 验证状态
     * @throws IOException 异常
     */
    public boolean checkSignature(String signature, String timestamp, String nonce) {
        return WeixinUtils.checkSignature(signature, timestamp, nonce);
    }

    /**
     * 跳转页面
     *
     * @param request 请求
     * @param menu    菜单配置值
     * @return 页面url
     * @throws IOException 异常
     */
    public String start(HttpServletRequest request, String menu) throws IOException {
        String redirectUrl = this.getAuth2APICode(request, menu);
        if (StringUtils.isBlank(redirectUrl)) {
            return "";
        }
        return "redirect:" + redirectUrl;
    }

    /**
     * 首页面
     *
     * @param code 微信用户code编码
     * @return 结果集
     * @throws IOException
     */
    public ModelAndView index(String code, String menu) throws IOException {
        ModelAndView mav = new ModelAndView();
        String openId = this.getOpenId(code);
        String token = "";
        if (StringUtils.isNotBlank(openId)) {
            mav.addObject("openId", openId);
            HYCUtils.setWeixinThismenuCache(menu);
            HYCUtils.setWeixinUserCodeCache(code);
            menu = StringUtils.isBlank(menu) ? WeixinConstant.WEIXIN_INDEX_OTHERWISE : menu;
            if (menu.equals("order-ship")) {
                menu += "/0";
            }
            mav.addObject("otherwise", menu);
            mav.setViewName("driver-weixin");
            // 获取用户信息
            SUserExample us = new SUserExample();
            us.createCriteria().andOpenIdEqualTo(openId).andUserTypeEqualTo(UserTypeEnum.OWNER.getValue());
            List<SUser> list = this.getUserMapper().selectByExample(us);
            SUser user = list.size() > 0 ? list.get(0) : null;
            if (null != user) {
                UserVo u = new UserVo(user.getId(), user.getPhone(), user.getPwd(), user.getOpenId(),
                        user.getEnable().equals(EnabledEnum.T.getValue()), user.getUserType());
                token = JwtUtils.generateToken(u,
                        HYCUtils.getConstantPropertiesLoader().getProperty(App.SECURE_KEY));
            }
            if (StringUtils.isBlank(token)) {
                String[] otenerwiseArray = WeixinConstant.WEIXIN_NO_CHECKED_OTHERWISE.split(",");
                boolean isExist = false;
                for (String s : otenerwiseArray) {
                    if (s.trim().equals(menu)) {
                        isExist = true;
                        break;
                    }
                }
                if (!isExist) {
                    mav.addObject("otherwise", WeixinConstant.WEIXIN_LOGIN_OTHERWISE);
                }
            }
            mav.addObject("token", this.resetToken(token));
        }
        return mav;
    }

    public Result<Object> sendWeixinTextMsg(WeixinTextMessageVo wtmv) throws IOException {
        Result<Object> r = new Result<Object>(true);
        String msgBody = JSONObject.toJSONString(wtmv);
        String url = HYCUtils.getConstantPropertiesLoader().getProperty(WeixinConstant.WEIXIN_MESSAGE_URL);
        url += WeixinUtils.getAccessToken();
        WeixinResultVo result = new WeixinResultVo(HttpUtils.weixinPost(url, msgBody));
        if (!result.isSuccess()) {
            r.setSuccess(false);
            r.setMessage(result.getErrmsg());
        }
        return r;
    }

    public Result<Object> sendWeixinNewsMsg(WeixinNewsMessageVo wnmv) throws IOException {
        Result<Object> r = new Result<Object>(true);
        String msgBody = JSONObject.toJSONString(wnmv);
        String url = HYCUtils.getConstantPropertiesLoader().getProperty(WeixinConstant.WEIXIN_MESSAGE_URL);
        url += WeixinUtils.getAccessToken();
        WeixinResultVo result = new WeixinResultVo(HttpUtils.weixinPost(url, msgBody));
        if (!result.isSuccess()) {
            r.setSuccess(false);
            r.setMessage(result.getErrmsg());
        }
        return r;
    }

    /**
     * 重新组合token
     *
     * @param token token值
     * @return
     */
    private String resetToken(String token) {
        if (StringUtils.isNotBlank(token) && !token.startsWith(JwtAuthenicationFilter.PREFIX_AUTHORIZATION)) {
            token = JwtAuthenicationFilter.PREFIX_AUTHORIZATION + token;
        }
        return token;
    }

    /**
     * 获取openid
     *
     * @param code 随机码
     * @return openid
     * @throws IOException
     */
    private String getOpenId(String code) throws IOException {
        String userInfoUrl;
        String weixinType = HYCUtils.getConstantPropertiesLoader().getProperty(WeixinConstant.WEIXIN_TYPE);
        // 企业号
        if (weixinType.equals(WeixinConstant.WEIXIN_QY_TYPE)) {
            userInfoUrl = HYCUtils.getConstantPropertiesLoader().getProperty(WeixinConstant.WEIXIN_QY_USERINFO_URL);
            userInfoUrl += WeixinUtils.getAccessToken();
        } else {
            userInfoUrl = HYCUtils.getConstantPropertiesLoader().getProperty(WeixinConstant.WEIXIN_USERINFO_URL);
        }
        // 获取结果集
        JSONObject j = HttpUtils.get(userInfoUrl + "&code=" + code);
        // 找出openid
        if (j.containsKey("UserId")) {
            String userId = j.getString("UserId");
            String url = HYCUtils.getConstantPropertiesLoader().getProperty(WeixinConstant.WEIXIN_USERID_2_OPENID_URL)
                    + "?access_token=" + WeixinUtils.getAccessToken();
            JSONObject params = new JSONObject();
            params.put("userid", userId);
            JSONObject resultObj = HttpUtils.weixinPost(url, params.toString());
            if (resultObj.containsKey("openid")) {
                return resultObj.getString("openid");
            }
        } else if (j.containsKey("OpenId")) {
            return j.getString("OpenId");
        } else if (j.containsKey("openid")) {
            return j.getString("openid");
        }
        return null;
    }

    /**
     * 获取重定向地址
     *
     * @param request 请求
     * @return 重定向地址
     * @throws IOException 异常
     */
    private String getAuth2APICode(HttpServletRequest request, String menu) throws IOException {
        // 拼接微信回调地址
        String backUrl = HttpUtils.getHostAddressWithContextPath() + "/weixin/index?menu=" + menu;
        String redirect_uri = "";
        redirect_uri = URLEncoder.encode(backUrl, "utf-8");
        return HYCUtils.getConstantPropertiesLoader().getProperty(WeixinConstant.WEIXIN_OPENID_URL) + "&redirect_uri=" + redirect_uri
                + "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
    }

    private SUserMapper getUserMapper() {
        return this.userMapper;
    }

}
